package com.fcat.base.common.util;

import java.sql.Time;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class DateUtil {
    public final static SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
    public final static SimpleDateFormat longSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    public static final int PRE_DAY_MILLISECOND = 24 * 60 * 60 * 1000;

    public static final long TIME_INTERVAL_MILLISECOND = 24L * 60 * 60 * 1000 * 92;

    private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC");
    private static final TimeZone BEIJING_TIME_ZONE = TimeZone.getTimeZone("Asia/Shanghai");
    private static final int UTC_TIME_ZONE_INT = 307;
    private static final int BEIJING_TIME_ZONE_INT = 521;

    public static final String TIME_PATTERN_DEFAULT = "yyyyMMddHHmmssSSS";
    public static final String TIME_PATTERN_DISPLAY_DEFAULT = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String TIME_PATTERN_DISPLAY = "yyyy-MM-dd HH:mm:ss";
    public static final String TIME_PATTERN_DISPLAY2 ="yyyy/MM/dd HH:mm:ss";
    public static final String TIME_PATTERN_DAY = "yyyy-MM-dd";
    public static final String TIME_PATTERN_YEAR_MONTH = "yyyy-MM";
    public static final String TIME_PATTERN_HH_mm = "HH:mm";
    public static final String TIME_PATTERN_HH_mm_ss = "HH:mm:ss";
    public static final String TIME_PATTERN_YMD = "yyyyMMdd";
    public static final String TIME_PATTERN_Hms = "HHmmss";
    public static final String TIME_PATTERN_SEARCH_DAY = "yyyy MM dd";
    public static final String TIME_PATTERN_DAY_SLASH = "yyyy/MM/dd";

    public static final int[] DAY_OF_MONTH_MAX = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    public static final long UTC_DATE_LONG_DEFAULT = 19700101L;
    public static final long UTC_DATETIME_LONG_DEFAULT = 19700101000000000L;

    public static final long VALID_MILLISECOND_SHORT = 2L * 60 * 1000;// 2分钟的有效期

    private DateUtil() {
    }

    public static TimeZone getTimeZone(Short timeZoneId) {
        return timeZoneId == null ? null : getTimeZone(timeZoneId.intValue());
    }

    public static TimeZone getTimeZone(int timeZoneIdInt) {
        return TimeZone.getDefault();
    }

    public static TimeZone getTimeZone(String timeZoneId) {
        return getTimeZone(timeZoneId);
    }

    public static TimeZone getUtcTimeZone() {
        return UTC_TIME_ZONE;
    }

    public static TimeZone getBeijinTimeZone() {
        return BEIJING_TIME_ZONE;
    }

    public static int getUtcTimeZoneInt() {
        return UTC_TIME_ZONE_INT;
    }

    public static int getBeijinTimeZoneInt() {
        return BEIJING_TIME_ZONE_INT;
    }

    public static Date toUtcDate(String s, String pattern) {
        return toDate(s, pattern, UTC_TIME_ZONE);
    }

    public static Date toUtcDate(String s) {
        return toDate(s, TIME_PATTERN_DEFAULT, UTC_TIME_ZONE);
    }

    /**
     * @param s UTC时间，格式:yyyyMMddHHmmssSSS
     * @return
     */
    public static Date toUtcDate(long s) {
        return toDate(String.valueOf(s), TIME_PATTERN_DEFAULT, UTC_TIME_ZONE);
    }

    /**
     * @param s        日期字符串
     * @param pattern  yyyy-MM-dd<br>
     *                 HH:mm:ss<br>
     *                 yyyy-MM-dd HH:mm:ss<br>
     *                 MM-dd<br>
     *                 HH:mm<br>
     *                 MM-dd HH:mm:ss<br>
     *                 yyyy-MM-dd HH:mm:ss.S<br>
     *                 yyyyMMdd<br>
     *                 yyyyMMddHHmmssS<br>
     *                 yyyyMMddHHmmssSSS<br>
     *                 MM-dd HH:mm<br>
     *                 yyyy-MM-dd HH:mm:ss <br>
     *                 yyyy-MM-dd HH:mm:ss.SSS<br>
     * @param timeZone 日期字符串对应的时区
     * @return 本地日期对象
     */
    public static Date toDate(String s, String pattern, TimeZone timeZone) {
        if (StrUtil.isBlank(pattern)) {
            pattern = "yyyy-MM-dd HH:mm:ss.SSS";
        }else if(pattern.equals(TIME_PATTERN_HH_mm)){
            s="1970-01-01 "+s+":00";
            pattern=TIME_PATTERN_DISPLAY;
        }else if(pattern.equals(TIME_PATTERN_HH_mm_ss)){
            s="1970-01-01 "+s;
            pattern=TIME_PATTERN_DISPLAY;
        }
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
            dateFormat.setTimeZone(timeZone);
            Date result = dateFormat.parse(s);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }



    public static Date toDate(String s, TimeZone timeZone) {
        return toDate(s, "yyyy-MM-dd HH:mm:ss.SSS", timeZone);
    }

    public static Date toDate(String s, String pattern) {
        return toDate(s, pattern, TimeZone.getDefault());
    }

    public static Date toDate(String s) {
        if (StrUtil.isBlank(s))
            return null;
        return toDate(s, "yyyyMMddHHmmssSSS", TimeZone.getDefault());
    }


    public static Date toDate(long s) {
        if (s == 0)
            return null;
        return toDate(s, "yyyyMMddHHmmssSSS", TimeZone.getDefault());
    }

    /**
     * @param s        日期字符串, yyyyMMdd|yyyyMMddHHmmssSSS,具体格式根据pattern来决定
     * @param pattern
     * @param timeZone 日期字符串对应的时区
     * @return
     */
    public static Date toDate(long s, String pattern, TimeZone timeZone) {
        return toDate(String.valueOf(s), pattern, timeZone);
    }

    /**
     * @param date     本地日期对象
     * @param pattern  yyyy-MM-dd<br>
     *                 HH:mm:ss<br>
     *                 yyyy-MM-dd HH:mm:ss<br>
     *                 MM-dd<br>
     *                 HH:mm<br>
     *                 MM-dd HH:mm:ss<br>
     *                 yyyy-MM-dd HH:mm:ss.S<br>
     *                 yyyyMMdd<br>
     *                 yyyyMMddHHmmssS<br>
     *                 MM-dd HH:mm<br>
     *                 yyyy-MM-dd HH:mm:ss.SSS<br>
     *                 yyyy-MM-dd HH:mm:ss<br>
     *                 yyyy年MM月dd日 HH:mm:ss<br>
     *                 yyyy年MM月dd日 HH:mm<br>
     * @param timeZone 格式化后的时间的时区
     * @return
     */
    public static String formatDate(Date date, String pattern, TimeZone timeZone) {
        if (StrUtil.isBlank(pattern)) {
            throw new NullPointerException("StringUtil.isBlank(pattern) pattern=" + pattern);
        }
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
            if (timeZone != null) {
                dateFormat.setTimeZone(timeZone);
            }
            return dateFormat.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String formatDate(String dateStr, String dateStrPattern, TimeZone timeZone, String pattern) {
        if (StrUtil.isBlank(pattern)) {
            throw new NullPointerException("StringUtil.isBlank(pattern) pattern=" + pattern);
        }
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat(dateStrPattern);
            if (timeZone != null) {
                dateFormat.setTimeZone(timeZone);
            }
            Date date = dateFormat.parse(dateStr);
            return formatDate(date, pattern, timeZone);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String formatDate(String dateStr, String dateStrPattern, int timeZoneIdInt, String pattern) {
        if (StrUtil.isBlank(pattern)) {
            throw new NullPointerException("StringUtil.isBlank(pattern) pattern=" + pattern);
        }
        try {
            TimeZone timeZone = getTimeZone(timeZoneIdInt);
            return formatDate(dateStr, dateStrPattern, timeZone, pattern);
        } catch (Exception e) {
           e.printStackTrace();
        }
        return "";
    }

    /**
     * @param date     本地日期对象
     * @param timeZone 格式化后的时间的时区
     * @return
     */
    public static String formatDate(Date date, TimeZone timeZone) {
        return formatDate(date, "yyyy-MM-dd HH:mm:ss.SSS", timeZone);
    }

    public static String formatDate(Date date, String pattern) {
        return formatDate(date, pattern, TimeZone.getDefault());
    }

    public static String formatDate(Date date) {
        return formatDate(date, "yyyy-MM-dd HH:mm:ss.SSS", TimeZone.getDefault());
    }

    /**
     * @param date          本地日期对象
     * @param timeZoneIdInt 格式化后的时间的时区
     * @return
     */
    public static String formatDate(Date date, int timeZoneIdInt) {
        return formatDate(date, "yyyy-MM-dd HH:mm:ss.SSS", getTimeZone(timeZoneIdInt));
    }

    /**
     * @return yyyyMMddHHmmssSSS
     */
    public static long getLongDate() {
        return formatDateToLong(new Date());
    }

    public static long getLongDate(Date date) {
        return formatDateToLong(date);
    }

    public static long formatDateToLong(Date date) {
        return formatDateToHbaseLong(date, BEIJING_TIME_ZONE);
    }

    public static long formatDateToHbaseLong(Date date, TimeZone timeZone) {
        String result = formatDate(date, TIME_PATTERN_DEFAULT, timeZone);
        return MathUtil.toLong(result);
    }

    public static long formatDateToHbaseUtc(Date date) {
        String result = formatDate(date, TIME_PATTERN_DEFAULT, UTC_TIME_ZONE);
        return MathUtil.toLong(result);
    }

    public static long formatDateForLongUtc(String date, String pattern) {
        return formatDateToHbaseUtc(toDate(date, pattern));
    }

    public static long formatDateToHbaseUtc() {
        String result = formatDate(new Date(), TIME_PATTERN_DEFAULT, UTC_TIME_ZONE);
        return MathUtil.toLong(result);
    }

    /**
     * @param utcLong       utcLong格式yyyyMMddHHmmssSSS
     * @param timeZoneIdInt 格式化后的时间的时区
     * @return
     */
    public static String formatDateHbaseUtcToDisplay(long utcLong, int timeZoneIdInt) {
        return formatDateHbaseUtcToDisplay(utcLong, TIME_PATTERN_DEFAULT, timeZoneIdInt, TIME_PATTERN_DISPLAY_DEFAULT);
    }

    /**
     * @param utcLong  utcLong格式yyyyMMddHHmmssSSS
     * @param timeZone 用户设定的时区
     * @return
     */
    public static String formatDateHbaseUtcToDisplay(long utcLong, TimeZone timeZone) {
        return formatDateHbaseUtcToDisplay(utcLong, TIME_PATTERN_DEFAULT, timeZone, TIME_PATTERN_DISPLAY_DEFAULT);
    }

    /**
     * @param dateLong utcLong格式yyyyMMddHHmmssSSS
     * @param timeZone 用户设定的时区
     * @return
     */
    public static String formatLongToDisplay(long dateLong, TimeZone timeZone, String pattern) {
        return formatDateToDisplay(dateLong, TIME_PATTERN_DEFAULT, timeZone, pattern);
    }

    /**
     * 根据用户设定的timeZoneIdInt，把utcLong(yyyyMMddHHmmssSSS)转化为显示的时间
     *
     * @param utcLong    数据库中保存的大部分都是yyyyMMddHHmmssSSS
     * @param patternUtc utcLong格式yyyyMMddHHmmssSSS
     * @param timeZone   用户设定的时区
     * @param pattern    转化为显示的时间格式
     * @return INIT_UTC_DATETIME_LONG||INIT_UTC_DATE_LONG直接返回""
     */
    public static String formatDateHbaseUtcToDisplay(long utcLong, String patternUtc, TimeZone timeZone, String pattern) {
        if (utcLong == UTC_DATETIME_LONG_DEFAULT || utcLong == UTC_DATE_LONG_DEFAULT) {
            return "";
        }
        if (StrUtil.isBlank(patternUtc)) {
            patternUtc = TIME_PATTERN_DEFAULT;
        }

        if (StrUtil.isBlank(pattern)) {
            pattern = TIME_PATTERN_DISPLAY_DEFAULT;
        }

        Date date = toDate(String.valueOf(utcLong), patternUtc, UTC_TIME_ZONE);
        String result = formatDate(date, pattern, timeZone);
        return result;
    }

    /**
     * 根据用户设定的timeZoneIdInt，把utcLong(yyyyMMddHHmmssSSS)转化为显示的时间
     *
     * @param dateLong    数据库中保存的大部分都是yyyyMMddHHmmssSSS
     * @param patternLong dateLong格式yyyyMMddHHmmssSSS
     * @param timeZone    用户设定的时区
     * @param pattern     转化为显示的时间格式
     * @return INIT_UTC_DATETIME_LONG||INIT_UTC_DATE_LONG直接返回""
     */
    public static String formatDateToDisplay(long dateLong, String patternLong, TimeZone timeZone, String pattern) {
        if (dateLong == UTC_DATETIME_LONG_DEFAULT || dateLong == UTC_DATE_LONG_DEFAULT) {
            return "";
        }
        if (StrUtil.isBlank(patternLong)) {
            patternLong = TIME_PATTERN_DEFAULT;
        }

        if (StrUtil.isBlank(pattern)) {
            pattern = TIME_PATTERN_DISPLAY_DEFAULT;
        }

        Date date = toDate(String.valueOf(dateLong), patternLong, BEIJING_TIME_ZONE);
        String result = formatDate(date, pattern, timeZone);
        return result;
    }

    /**
     * @param date    北京时间
     * @param pattern 显示模版
     * @return
     */
    public static String formatDateToDisplay(Date date, String pattern) {
        if (StrUtil.isBlank(pattern)) {
            pattern = TIME_PATTERN_DISPLAY_DEFAULT;
        }
        String result = formatDate(date, pattern, BEIJING_TIME_ZONE);
        return result;
    }

    /**
     * 根据用户设定的timeZoneIdInt，把utcLong(yyyyMMddHHmmssSSS)转化为显示的时间
     *
     * @param utcLong       数据库中保存的大部分都是yyyyMMddHHmmssSSS
     * @param patternUtc    utcLong格式yyyyMMddHHmmssSSS
     * @param timeZoneIdInt 用户设定的时区
     * @param pattern       转化为显示的时间格式
     * @return INIT_UTC_DATETIME_LONG||INIT_UTC_DATE_LONG直接返回""
     */
    public static String formatDateHbaseUtcToDisplay(long utcLong, String patternUtc, int timeZoneIdInt, String pattern) {
        return formatDateHbaseUtcToDisplay(utcLong, patternUtc, getTimeZone(timeZoneIdInt), pattern);
    }

    /**
     * @param dateStr
     * @param pattern
     * @param sourceTimeZone
     * @return
     */
    public static Date toAnotherTimeZone(String dateStr, String pattern, TimeZone sourceTimeZone, TimeZone targetTimeZone) {
        try {
            Date sourceDate = toDate(dateStr, pattern, sourceTimeZone);
            String targetDateStr = formatDate(sourceDate, pattern, targetTimeZone);
            return toDate(targetDateStr, pattern, targetTimeZone);
        } catch (Exception e) {
           e.printStackTrace();
        }
        return null;
    }

    public static Date toAnotherTimeZone(Date date, TimeZone sourceTimeZone, TimeZone targetTimeZone) {
        try {
            String sourceDateStr = formatDate(date, TIME_PATTERN_DISPLAY_DEFAULT, sourceTimeZone);
            return toAnotherTimeZone(sourceDateStr, TIME_PATTERN_DISPLAY_DEFAULT, sourceTimeZone, targetTimeZone);
        } catch (Exception e) {
           e.printStackTrace();
        }
        return null;
    }

    public static void printTimeZoneAvailableIDs() {
        String[] ids = TimeZone.getAvailableIDs();
        TimeZone timeZone;

        for (int i = 0; i < ids.length; i++) {
            System.out.println("");
            timeZone = TimeZone.getTimeZone(ids[i]);
            if (timeZone.equals(TimeZone.getDefault())) {
            }
        }
    }

    public static void printAvailableLocales() {
        Locale[] localeArr = Locale.getAvailableLocales();
    }

    public static Date nullToDate(Date date) {
        if (date == null) {
            return new Date();
        }
        return date;
    }

    /**
     * @param date
     * @param amount
     * @param unit   Calendar.YEAR=1 Calendar.MONTH=2 Calendar.DATE=5 <br>
     *               Calendar.HOUR=10 Calendar.MINUTE=12 Calendar.SECOND=13
     *               Calendar.MILLISECOND=14
     * @return
     */
    public static Date toAnotherDate(Date date, long amount, int unit) {
        if (date == null) {
            throw new NullPointerException("date == null");
        }
        if (unit == 14) {
            return new Date(date.getTime() + amount);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(unit, (int) amount);
        return calendar.getTime();
    }

    public static Date toAnotherDate(long amount, int unit) {
        return toAnotherDate(new Date(), amount, unit);
    }

    /**
     * @param dateAnother
     * @param birthDate
     * @return
     */
    public static int getAge(Date dateAnother, Date birthDate) {
        if (dateAnother == null) {
            dateAnother = new Date();
        }
        if (birthDate == null) {
            birthDate = new Date();
        }
        return getYear(dateAnother) - getYear(birthDate);
    }

    /**
     * @param date
     * @return
     */
    public static int getYear(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    /**
     * @param date
     * @return
     */

    public static int getWeek(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(3);
    }

    public static int getWeek() {
        return getWeek(null);
    }

    public static int getYearWeek(Date date) {
        if (date == null) {
            date = new Date();
        }
        int yearInt = getYear(date);
        int weekInt = getWeek(date);
        return yearInt * 100 + weekInt;
    }

    public static int getYearWeek() {
        return getYearWeek(null);
    }

    /**
     * 返回给定月份的最大日期
     *
     * @param year  year >0
     * @param month [0,11]
     * @return
     */
    public static int getDayOfMonthMax(int year, int month) {
        if (year < 1) {
            throw new IllegalArgumentException("getDayOfMonthMax(int year, int month) year < 1 year=" + year + " month=" + month);
        }
        if (month < 0 || month > 11) {
            throw new IllegalArgumentException("getDayOfMonthMax(int year, int month) month < 0 || month > 11 year=" + year + " month=" + month);
        }

        if (month != 2) {
            return DAY_OF_MONTH_MAX[month];
        } else {// 四年一闰；百年不闰,四百年再闰。
            if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {// 闰年
                return 29;
            }
            return 28;
        }
    }

    /**
     * @param startTime UTC时间，格式:yyyyMMddHHmmssSSS
     * @param endTime   UTC时间，格式:yyyyMMddHHmmssSSS
     * @return 缩小后的endTime
     */
    public static long shrinkTimeInterval(long startTime, long endTime) {
        return shrinkTimeInterval(startTime, endTime, TIME_INTERVAL_MILLISECOND);
    }

    /**
     * 自动缩小时间区间
     *
     * @param startTime       UTC时间，格式:yyyyMMddHHmmssSSS
     * @param endTime         UTC时间，格式:yyyyMMddHHmmssSSS
     * @param timeIntervalMax 允许的最大毫秒数
     * @return 缩小后的endTime
     */
    public static long shrinkTimeInterval(long startTime, long endTime, long timeIntervalMax) {
        if (startTime < endTime) {
            Date startTimeDate = toDate(String.valueOf(startTime), TIME_PATTERN_DEFAULT, UTC_TIME_ZONE);
            Date endTimeDate = toDate(String.valueOf(endTime), TIME_PATTERN_DEFAULT, UTC_TIME_ZONE);
            if (endTimeDate.getTime() - startTimeDate.getTime() > timeIntervalMax) {
                startTimeDate.setTime(startTimeDate.getTime() + timeIntervalMax);
                long endTimeShrink = MathUtil.toLong(formatDate(startTimeDate, TIME_PATTERN_DEFAULT, UTC_TIME_ZONE));
                endTime = endTimeShrink;
            }
        }
        return endTime;
    }

    /**
     * 判断有效期<br>
     * expire 期满；文件、协议等（因到期而）失效；断气；逝世
     *
     * @param timeLongUtc yyyyMMddHHmmssSSS
     * @return true=有效期内 false=失效
     */
    public static boolean expiryDateCheck(String timeLongUtc) {
        return expiryDateCheck(timeLongUtc, VALID_MILLISECOND_SHORT);
    }

    public static boolean expiryDateCheck(String timeLongUtc, long validMillisecond) {
        Date dateUtc = DateUtil.toDate(timeLongUtc, TIME_PATTERN_DEFAULT, getUtcTimeZone());
        Date dateNowLocal = new Date();
        return (dateNowLocal.getTime() - dateUtc.getTime() <= validMillisecond);
    }

    public static long utcDateAdd(long millisecond) {
        Date date = new Date();
        date.setTime(date.getTime() + millisecond);
        String result = formatDate(date, TIME_PATTERN_DEFAULT, UTC_TIME_ZONE);
        return MathUtil.toLong(result);
    }

    public static Date currDateAdd(Date currDate, long millisecond) {
        Date newDate = new Date();
        if (currDate == null)
            return null;
        newDate.setTime(currDate.getTime() + millisecond);
        return newDate;
    }

    /**
     * calculateRemainTime 计算剩余时间: xx天xx小时xx分钟(xx秒钟)
     *
     * @param expiredDate 失效时间
     * @param showSecond  显示秒钟
     * @return
     * @author jonex 2015年4月16日
     */
    public static String calculateRemainTime(Date expiredDate, boolean showSecond) {
        Calendar expiredCalendar = Calendar.getInstance();
        expiredCalendar.setTime(expiredDate);
        Calendar currentCalendar = Calendar.getInstance();
        currentCalendar.setTime(new Date());
        StringBuffer buffer = new StringBuffer();
        long expiredTime = expiredCalendar.getTimeInMillis();
        long currentTime = currentCalendar.getTimeInMillis();
        long dif = Math.abs(expiredTime - currentTime);
        int days = new Long(dif / (1000 * 60 * 60 * 24)).intValue();
        if (days != 0) {
            buffer.append(days).append("天");
        }
        int hours = new Long((dif % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)).intValue();
        if (hours != 0) {
            buffer.append(hours).append("小时");
        }
        int minutes = new Long(((dif % (1000 * 60 * 60 * 24)) % (1000 * 60 * 60)) / (1000 * 60)).intValue();
        if (hours != 0) {
            buffer.append(minutes).append("分钟");
        }
        int seconds = new Long(((((dif % (1000 * 60 * 60 * 24)) % (1000 * 60 * 60))) % (1000 * 60)) / 1000).intValue();
        if ((hours == 0 || showSecond) && seconds != 0) {
            buffer.append(seconds).append("秒");
        }
        return buffer.toString();
    }

    /**
     * 获取今天还剩下多少秒
     *
     * @return
     */
    public static int getMiao() {
        Calendar curDate = Calendar.getInstance();
        Calendar tommorowDate = new GregorianCalendar(curDate.get(Calendar.YEAR), curDate.get(Calendar.MONTH), curDate.get(Calendar.DATE) + 1, 0, 0, 0);
        return (int) (tommorowDate.getTimeInMillis() - curDate.getTimeInMillis()) / 1000;
    }

    public static int getMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        if (date != null) cal.setTime(date);
        int month = cal.get(Calendar.MONTH) + 1;
        return month;
    }

    public static int getDay(Date date) {
        Calendar cal = Calendar.getInstance();
        if (date != null) cal.setTime(date);
        int day = cal.get(Calendar.DATE);
        return day;
    }

    /**
     * 日期统一格式化，把xxxx年xx月xx日统一为xxxx-xx-xx
     *
     * @param dateStr
     * @return
     */
    public static String dateFormatUnify(String dateStr) {
        if (StrUtil.isBlank(dateStr)) {
            return dateStr;
        }
        String year = "";
        String month = "";
        String date = "";
        StringBuilder dateResult = new StringBuilder();
        int yearIndex = dateStr.indexOf("年");
        int charIndex = dateStr.indexOf("-");
        if (yearIndex > 0) {
            year = dateStr.substring(0, yearIndex);
            dateStr = dateStr.substring(yearIndex + 1);
            int monthIndex = dateStr.indexOf("月");
            if (monthIndex > 0) {
                month = dateStr.substring(0, monthIndex);
                dateStr = dateStr.substring(monthIndex + 1);
            }
            int dateIndex = dateStr.indexOf("日");
            if (dateIndex > 0) {
                date = dateStr.substring(0, dateIndex);
            }
        } else {
            if (charIndex > 0) {
                String[] dateStrs = dateStr.split("-");
                if (dateStrs.length > 2) {
                    year = dateStrs[0];
                    month = dateStrs[1];
                    date = dateStrs[2];
                }
            }
        }
        if (year.trim().length() == 4) {
            dateResult.append(year.trim());
            dateResult.append("-");
        }

        if (month.trim().length() == 1) {
            dateResult.append("0" + month.trim());
            dateResult.append("-");
        } else if (month.trim().length() == 2) {
            dateResult.append(month.trim());
            dateResult.append("-");
        }

        if (date.trim().length() == 1) {
            dateResult.append("0" + date.trim());
            dateResult.append("-");
        } else if (date.trim().length() == 2) {
            dateResult.append(date.trim());
            dateResult.append("-");
        }
        if (dateResult.charAt(dateResult.length() - 1) == '-') {
            dateResult.deleteCharAt(dateResult.length() - 1);
        }
        return dateResult.toString();
    }

    /**
     * 得到当前时间的前N天
     *
     * @param date
     * @param beforeDay 前几天
     * @return long yyyyMMddHHmmssSSS 格式
     */
    public static long getSpecifiedDayBefore(Date date, int beforeDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int day = calendar.get(Calendar.DATE);
        calendar.set(Calendar.DATE, day - beforeDay);
        return getLongDate(calendar.getTime());
    }

    public static Date getTodayWithStr(Date date, String hourMinuteSecondStr) {
        String formatDate = DateUtil.formatDate(date, DateUtil.TIME_PATTERN_DAY) + hourMinuteSecondStr;
        Date todayMorning = DateUtil.toDate(formatDate, DateUtil.TIME_PATTERN_DISPLAY);
        return todayMorning;
    }

    public static int getMonthDiff(Date date, Date anotherDate) {
        int start = getMonth(date);
        int end = getMonth(anotherDate);
        return Math.abs(start - end);
    }

    public static long getTimeDiff(Date date, Date anotherDate) {
        long timeDiff = date.getTime() - anotherDate.getTime();
        return timeDiff;
    }

    public static Date getLastDayOfMonth(Date date) {
        int dayOfMonthMax = getDayOfMonthMax(date.getYear(), date.getMonth());
        int day = getDay(date);
        Date anotherDate = DateUtil.toAnotherDate(date, dayOfMonthMax - day, Calendar.DATE);
        //System.out.println(formatDate(anotherDate,DateUtil.TIME_PATTERN_DISPLAY));
        return anotherDate;
    }

    public static Date getLargestMonth(Date date) {

        int dayOfMonthMax = getDayOfMonthMax(date.getYear(), date.getMonth());
        int day = getDay(date);
        Date anotherDate = DateUtil.toAnotherDate(date, dayOfMonthMax - day, Calendar.DATE);
        String formatDate = formatDate(anotherDate, TIME_PATTERN_DISPLAY);
        formatDate = formatDate.substring(0, 11) + "23:59:59";
        return toDate(formatDate, TIME_PATTERN_DISPLAY);
    }

    public static String getMonthDate(Integer month) {
        Date date = new Date();
        int month2 = month - DateUtil.getMonth(date);
        System.out.println(DateUtil.getMonth(date));
        System.out.println(month);
        Date anotherDate = DateUtil.toAnotherDate(date, month2, Calendar.MONTH);
        String formatDate = formatDate(anotherDate, "yyyy-MM");
        return formatDate;
    }

    public static Date getMinestMonth(Date date) {
        String formatDate = formatDate(date, TIME_PATTERN_DISPLAY);
        formatDate = formatDate.substring(0, 8) + "01 00:00:00";
        return toDate(formatDate, TIME_PATTERN_DISPLAY);
    }

	/*public static void main(String[] args){
        Date startTime = new Date();
		Date anotherDate = DateUtil.toAnotherDate(startTime, 2, Calendar.MONTH);
		String str = DateUtil.formatDate(anotherDate, DateUtil.TIME_PATTERN_DISPLAY);
			Date largestMonth = DateUtil.getLargestMonth(anotherDate);
		String str1 = DateUtil.formatDate(largestMonth, DateUtil.TIME_PATTERN_DISPLAY);
			Date endTime = DateUtil.getTodayWithStr(anotherDate, " 23:59:59");
		String str2 = DateUtil.formatDate(endTime, DateUtil.TIME_PATTERN_DISPLAY);

		System.out.println(formatDate(getLargestMonth(new Date()),DateUtil.TIME_PATTERN_DISPLAY));
		for (int i = 1; i < 13; i++) {
			Integer tempMonth = i % 3;
			Integer monthDiff = 0;
			if(tempMonth == 1){
				monthDiff = 2;
			}else if(tempMonth == 2){
				monthDiff = 1;
			}
			System.out.println(i + "." + (i + monthDiff));

		}
		Date anotherDate = DateUtil.toAnotherDate(startTime, monthDiff, Calendar.MONTH);

		System.out.println(formatDate(getMinestMonth(new Date()),DateUtil.TIME_PATTERN_DISPLAY));
		//System.out.println(formatDate(getLastDayOfMonth(new Date()),DateUtil.TIME_PATTERN_DISPLAY));
		Calendar calendar = Calendar.getInstance();
		Date date = new Date();
		date = toAnotherDate(date, -4, Calendar.DAY_OF_WEEK);
		Date anotherDate1 = toAnotherDate(date, 6, Calendar.DATE);
		System.out.println(formatDate(anotherDate1,DateUtil.TIME_PATTERN_DISPLAY));
		System.out.println(anotherDate1);
		System.out.println(calendar.get(Calendar.DAY_OF_WEEK));
		for (int i = 0; i < 5; i++) {
			Date anotherDate = toAnotherDate(date, i, Calendar.DATE);
			System.out.println(formatDate(anotherDate,DateUtil.TIME_PATTERN_DISPLAY));
		}
		System.out.println();
	}*/

    /*
    获取2个时间节点之间的天数
     */
    public static int differentDays(Date date1, Date date2) {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(date1);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(date2);

        int day1 = calendar1.get(Calendar.DAY_OF_YEAR);
        int day2 = calendar2.get(Calendar.DAY_OF_YEAR);
        int year1 = calendar1.get(Calendar.YEAR);
        int year2 = calendar2.get(Calendar.YEAR);

        if (year1 != year2)  //不同年
        {
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) { //闰年
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {
                    timeDistance += 366;
                } else { // 不是闰年
                    timeDistance += 365;
                }
            }
            return timeDistance + (day2 - day1);
        } else {// 同年
            return day2 - day1;
        }
    }

    public static int differentDayMillisecond(Date date1, Date date2) {
        int day = (int) ((date2.getTime() - date1.getTime()) / (3600 * 1000 * 24));
        return day;
    }

    public static List<String> getMonthBetween(String minDate, String maxDate) throws ParseException {
        ArrayList<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月
        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();
        min.setTime(sdf.parse(minDate));
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);
        max.setTime(sdf.parse(maxDate));
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);
        Calendar curr = min;
        while (curr.before(max)) {
            result.add(sdf.format(curr.getTime()));
            curr.add(Calendar.MONTH, 1);
        }
        return result;
    }
    /**
     * 获取指定年的开始时间
     *
     * @return
     */
    public static Date getAppointYearStartTime(Integer year) {
        Calendar c = Calendar.getInstance();
        Date now = null;
        try {
            c.set(Calendar.YEAR,year);
            c.set(Calendar.MONTH, 0);
            c.set(Calendar.DATE, 1);
            now = shortSdf.parse(shortSdf.format(c.getTime()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return now;
    }
    /**
     * 当前指定年的结束时间
     *
     * @return
     */
    public static Date getAppointYearEndTime(Integer year) {
        Calendar c = Calendar.getInstance();
        Date now = null;
        try {
            c.set(Calendar.YEAR,year);
            c.set(Calendar.MONTH, 11);
            c.set(Calendar.DATE, 31);
            now = longSdf.parse(shortSdf.format(c.getTime()) + " 23:59:59");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return now;
    }

    /**
     *
     * @param now
     * @return
     */

    /**
     * 指定修改时间的位置 年月日 时分秒
     * @param now 要修改的时间
     * @param param Calendar 静态成员变量
     * @param date 修改位置的参数
     * @return 修改之后的时间   报错返回当前时间
     */
    public static Date updateDate(Date now,int param,Integer date){
        Date result=null;
        Calendar c =Calendar.getInstance();
        c.setTime(now);
        c.set(param,date);
        try {
            result=shortSdf.parse(shortSdf.format(c.getTime()));
            return result;
        } catch (ParseException e) {
            e.printStackTrace();
            return now;
        }
    }


    /**
     * 计算两个时间相差的天数
     * @param endTime
     * @param startTime
     * @return  -1代表计算失败
     */
    public static Long daysDpart(Date endTime,Date startTime){
        if(endTime!=null && startTime!=null && endTime.getTime()>startTime.getTime()){
            long day = (long)((endTime.getTime() - startTime.getTime()) / (1000 * 60 * 60 *24) + 0.5);
            return day;
        }else{
            return Long.valueOf(-1);
        }


    }
    public static int getMinute(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MINUTE);
    }

    public static int getHour(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.HOUR_OF_DAY);
    }
    public static int getHour(Time time){
        if(time==null){
            return 0;
        }
        DateFormat sdf = new SimpleDateFormat("HH");
        return Integer.parseInt(sdf.format(time));
    }
    public static int getMinite(Time time){
        if(time==null){
            return 0;
        }
        DateFormat sdf = new SimpleDateFormat("mm");
        return Integer.parseInt(sdf.format(time));
    }
    public static int getRoundingHour(Date date){
        int minute=getMinute(date);
        int hour=getHour(date);
        if(minute>30){
            hour++;
        }
        return hour;
    }



    /**
     * 获取指定时间的0时区时间
     * @param beforeDate
     * @param dataFormat
     * @return 字符串
     */
    public static String getUTCTimeStr(Date beforeDate, String dataFormat) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dataFormat);
        // 1、取得本地时间：
        Calendar cal = Calendar.getInstance();
        cal.setTime(beforeDate);
        // 2、取得时间偏移量：
        int zoneOffset = cal.get(Calendar.ZONE_OFFSET);
        // 3、取得夏令时差：
        int dstOffset = cal.get(Calendar.DST_OFFSET);
        // 4、从本地时间里扣除这些差量，即可以取得UTC时间：
        cal.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset));
        Date afterDate = cal.getTime();
        try {
            return simpleDateFormat.format(afterDate);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取指定时间的0时区时间
     * @param beforeDate
     * @return  Date
     */
    public static Date getUTCTime(Date beforeDate) {
        // 1、取得本地时间：
        Calendar cal = Calendar.getInstance();
        cal.setTime(beforeDate);
        // 2、取得时间偏移量：
        int zoneOffset = cal.get(Calendar.ZONE_OFFSET);
        // 3、取得夏令时差：
        int dstOffset = cal.get(Calendar.DST_OFFSET);
        // 4、从本地时间里扣除这些差量，即可以取得UTC时间：
        cal.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset));
        Date afterDate = cal.getTime();
        return afterDate;
    }

    /**
     * 判断两个时间是否是一天
     * @param date1
     * @param date2
     * @return
     */
    public static boolean isSameDay(Date date1, Date date2) {
        if(date1 != null && date2 != null) {
            Calendar cal1 = Calendar.getInstance();
            cal1.setTime(date1);
            Calendar cal2 = Calendar.getInstance();
            cal2.setTime(date2);
            return isSameDay(cal1, cal2);
        } else {
            throw new IllegalArgumentException("The date must not be null");
        }
    }
    /**
     * 判断两个时间是否是一天
     * @param
     * @param
     * @return
     */
    public static boolean isSameDay(Calendar cal1, Calendar cal2) {
        if(cal1 != null && cal2 != null) {
            return cal1.get(0) == cal2.get(0) && cal1.get(1) == cal2.get(1) && cal1.get(6) == cal2.get(6);
        } else {
            throw new IllegalArgumentException("The date must not be null");
        }
    }

    /**
     * 获取指定时间段内的所有日期
     * @param dBegin 开始日期
     * @param dEnd 结束日期
     * @param pattern 日期格式
     * @return  yyyy-MM-dd
     */
    public static  List<String> findDates(Date dBegin, Date dEnd,String pattern){
        List<String> lDate = new ArrayList<String>();
        SimpleDateFormat sd = new SimpleDateFormat(pattern);
        lDate.add(sd.format(dBegin));
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime()))
        {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            lDate.add(sd.format(calBegin.getTime()));
        }
        return lDate;
    }

    /**
     * 获取日期的前n天的日期
     * @param date
     * @param days
     * @return
     */
    public static Date getBeforeDay(Date date,int days){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int day = calendar.get(Calendar.DATE);
        calendar.set(Calendar.DATE, day - days);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND,0);
        return calendar.getTime();
    }
    // 日期转化为大小写
    public static String dateToUpper(Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        int year = ca.get(Calendar.YEAR);
        int month = ca.get(Calendar.MONTH) + 1;
        int day = ca.get(Calendar.DAY_OF_MONTH);
        return numToUpper(year) + "年" + monthToUppder(month) + "月" + dayToUppder(day) + "日";
    }
    // 将数字转化为大写（字体格式可自己定义）
    public static String numToUpper(int num) {
        //String u[] = {"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
        String u[] = {"零","一","二","三","四","五","六","七","八","九"};
        char[] str = String.valueOf(num).toCharArray();
        String rstr = "";
        for (int i = 0; i < str.length; i++) {
            rstr = rstr + u[Integer.parseInt(str[i] + "")];
        }
        return rstr;
    }

    // 月转化为大写
    public static String monthToUppder(int month) {
        if(month < 10) {
            return numToUpper(month);
        } else if(month == 10){
            return "十";
        } else {
            return "十" + numToUpper(month - 10);
        }
    }

    // 日转化为大写
    public static String dayToUppder(int day) {
        if(day < 20) {
            return monthToUppder(day);
        } else {
            char[] str = String.valueOf(day).toCharArray();
            if(str[1] == '0') {
                return numToUpper(Integer.parseInt(str[0] + "")) + "十";
            }else {
                return numToUpper(Integer.parseInt(str[0] + "")) + "十" + numToUpper(Integer.parseInt(str[1] + ""));
            }
        }
    }

    /*
    获取日期当天的最早的值
     */
    public static Date getDayEarlyTime(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int day = calendar.get(Calendar.DATE);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND,0);
        return calendar.getTime();
    }

    /*
  获取日期当天的最晚的值
   */
    public static Date getDayLateTime(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int day = calendar.get(Calendar.DATE);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE,59);
        calendar.set(Calendar.SECOND,59);
        calendar.set(Calendar.MILLISECOND,0);
        return calendar.getTime();
    }


    /**
     * 获取当前月第一天的最早的时间
     * @return
     */
    public static Date getThisMonthEarlyTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND,0);
        return calendar.getTime();
    }

    /**
     * 获取上一月月第一天的最早的时间
     * @return
     */
    public static Date getPreMonthEarlyTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND,0);
        return calendar.getTime();
    }
    /**
     * 获取当上一月最晚的时间
     * @return
     */
    public static Date getPreMonthLateTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE,59);
        calendar.set(Calendar.SECOND,59);
        calendar.set(Calendar.MILLISECOND,0);
        return calendar.getTime();
    }


    /**
     * 获取本周一的值
     * @param date
     * @return
     */
    public static Date getThisWeekMonday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        // 获得当前日期是一个星期的第几天
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        // 获得当前日期是一个星期的第几天
        int day = cal.get(Calendar.DAY_OF_WEEK);
        // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
        return cal.getTime();
    }


    /**
     * 获取上周一的时间
     * @return
     */
    public static Date getPreWeekMonday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(getThisWeekMonday(date));
        calendar.add(Calendar.DATE, -7);
        return calendar.getTime();
    }

    /**
     * 获取上周日的时间
     * @return
     */
    public static Date getPreWeekSunday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(getThisWeekMonday(date));
        calendar.add(Calendar.DATE, -1);
        return calendar.getTime();
    }



    public static boolean inTimeRegion(Date startDate, Date endDate, Date compareDate) {
        if (startDate == null || endDate == null) {
            return false;
        }
        int sysHour = DateUtil.getHour(compareDate);
        int sysMinute = DateUtil.getMinute(compareDate);
        int startHour = DateUtil.getHour(startDate);
        int startMinute = DateUtil.getMinute(startDate);
        int endHour = DateUtil.getHour(endDate);
        int endMinute = DateUtil.getMinute(endDate);

        if ((startHour == endHour) && (startMinute == endMinute)) {
            return true;
        }


        if (startHour > endHour) {//说明跨凌晨的，也就是跨天
            if ((startHour > sysHour && sysHour > endHour)
                    || (startHour == sysHour && startMinute > sysMinute)
                    || (endHour == sysHour && endMinute < sysMinute)) {
                return false;
            }
        } else if ((startHour == endHour) && (startMinute > endMinute)) {//相同的时间，说明不需要监控的区域就是这个时间点，end-start的时间
            if (startHour == sysHour && sysMinute > endMinute && sysMinute < startMinute) {
                return false;
            }
        } else {
            if ((sysHour < startHour)
                    || (sysHour == startHour && sysMinute < startMinute)
                    || (sysHour > endHour)
                    || (sysHour == endHour && sysMinute > endMinute)) {
                return false;
            }
        }
        return true;
    }


    /**
     * 加小时数，可以为正，可以为负
     * @return
     */
    public static Date subHour(Date date,int hour) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR, hour);
        return calendar.getTime();
    }

    /**
     * 加毫秒数，可以为正，可以为负
     * @return
     */
    public static Date subSecond(Date date,int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, second);
        return calendar.getTime();
    }



    public static void main(String[] args) {
        Date sysDate=new Date();
        Date date=getThisWeekMonday(sysDate);
        date=getDayEarlyTime(date);
        System.err.println("本周最早的时间 "+formatDate(date,TIME_PATTERN_DISPLAY));

        date=getPreWeekMonday(sysDate);
        date=getDayEarlyTime(date);
        System.err.println("上周最早的时间 "+formatDate(date,TIME_PATTERN_DISPLAY));

        date=getPreWeekSunday(sysDate);
        date=getDayLateTime(date);
        System.err.println("上周最晚的时间 "+formatDate(date,TIME_PATTERN_DISPLAY));

    }

    public static String getGreenwichTime(Date date){
        if(date==null){
            return null;
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        format.setTimeZone(TimeZone.getTimeZone("GMT" + 0));  //nowTimeZone eg:+8，0，+9，-1 等等
        String str = format.format(date);
        return str;
    }

}